<?php

namespace System\Lib;

use System\Core\Config;
use System\Types\Object;
use System\Core\Applications;
use \System\Types;

/**
 * Description of Log
 *
 * @author elton.schivei
 */
class Log extends Object
{

    protected $_log_path;
    protected $_threshold = 1;
    protected $_date_fmt = 'Y-m-d H:i:s';
    protected $_enabled = true;

    const ERROR = 1;
    const DEBUG = 2;
    const INFO = 3;
    const ALL = 4;

    protected $_levels = array(
        'ERROR' => self::ERROR,
        'DEBUG' => self::DEBUG,
        'INFO' => self::INFO,
        'ALL' => self::ALL
    );

    /**
     * @var Log
     */
    private static $_instance;

    /**
     * Constructor
     * @access private
     */
    function __construct()
    {
        $configs = Config::Get(Config::LOGS);

        $this->_log_path = ($configs->Get('log_path')->Valor != '') ? $configs->Get('log_path')->Valor :
                Applications::GetAppPath() . 'logs/';

        if (!\is_dir($this->_log_path) OR !File::IsReallyWritable($this->_log_path))
        {
            $this->_enabled = false;
        }

        if (\is_numeric($configs->Get('log_threshold')->Valor))
        {
            $this->_threshold = $configs->Get('log_threshold')->Valor;
        }

        if ($configs->Get('log_date_format')->Valor != '')
        {
            $this->_date_fmt = $configs->Get('log_date_format')->Valor;
        }
    }

    /**
     * @return Log
     */
    public static function &GetInstance()
    {
        if (!self::$_instance)
            self::$_instance = new self();

        return self::$_instance;
    }

    /**
     * Write Log File
     *
     * @param	string	the error level
     * @param	string	the error message
     * @param	bool	whether the error is a native PHP error
     * @return	bool
     */
    public static function Write($msg, $level = 'error', $php_error = false)
    {
        return self::GetInstance()->WriteLog($msg, $level, $php_error);
    }

    /**
     * Read Log File
     *
     * @return Errors\Error Array
     */
    public static function Read()
    {
        return self::GetInstance()->ReadLog();
    }

    /**
     * Write Log File
     *
     * @param	string	the error level
     * @param	string	the error message
     * @param	bool	whether the error is a native PHP error
     * @return	bool
     */
    public function WriteLog($msg, $level = 'error', $php_error = false)
    {
        if (\is_numeric($level))
        {
            switch ($level)
            {
                case self::DEBUG:
                    $level = 'debug';
                    break;
                case self::INFO:
                    $level = 'info';
                    break;
                case self::ALL:
                    $level = 'all';
                    break;

                default:
                    $level = 'error';
                    break;
            }
        }

        if ($this->_enabled === false)
        {
            return false;
        }

        $level = \strtoupper($level);

        if (!isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
        {
            return false;
        }

        $filepath = $this->_log_path . 'log-' . \date('Y-m-d') . \EXT;
        $message = '';

        if (!\file_exists($filepath))
        {
            $message .= "<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?>\n\n";
        }

        if (!$fp = @\fopen($filepath, File::FOPEN_WRITE_CREATE))
        {
            return false;
        }

        $message .= $level . ' ' . (($level == 'INFO') ? ' -' : '-') . ' ' . \date($this->_date_fmt) . ' --> '
                . $msg . "\n";

        \flock($fp, \LOCK_EX);
        \fwrite($fp, $message);
        \flock($fp, \LOCK_UN);
        \fclose($fp);

        @\chmod($filepath, File::FILE_WRITE_MODE);
        return true;
    }

    /**
     * Read Log File
     *
     * @return Errors\Error Array
     */
    public function ReadLog()
    {
        if ($this->_enabled === false)
        {
            return array();
        }

        \date_default_timezone_set("America/Sao_Paulo");

        $filepath = $this->_log_path . 'log-' . \date('Y-m-d') . \EXT;

        if (!\file_exists($filepath))
        {
            return array();
        }

        if (!$fp = @\fopen($filepath, File::FOPEN_WRITE_CREATE))
        {
            return array();
        }

        $logs = \fread($fp, \filesize($filepath));

        $logs = \preg_replace('/^(\<\?)(.*)(\?\>\n\n)/i', '', $logs);

        $logs = \explode("\n", $logs);

        /* @var $Logs Errors\Error */
        $Logs = array();

        foreach ($logs as $log)
        {
            $Logs[] = new \Exception($log);
        }

        return $Logs;
    }

}
